/**
 * @file
 * @author dousha 
 * @date 2020/12/5.
 */

#include "hmac.h"
#include <sm3.h>
#include <string.h>

static uint8_t buf[96] = {0};
static uint8_t keyPrime[64] = {0};
static uint64_t targetByteLength = 0, processedLength = 0, messageLength = 0;

void hmac_key_prime(const uint8_t *key, uint16_t keyLength) {
	if (keyLength > 64) {
		processedLength = 0;
		targetByteLength = sm3_get_padded_byte_length(keyLength);
		while (processedLength < targetByteLength) {
			for (uint8_t i = 0; i < 64; i++) {
				buf[i] = processedLength + i < keyLength ? key[processedLength + i] : 0;
			}
			sm3_update(buf, processedLength, keyLength * 8);
			processedLength += 64;
		}
		memcpy(buf, sm3_finalize(), 32);
		for (uint8_t i = 0; i < 32; i++) {
			keyPrime[i] ^= 0x36u;
		}
		memset(keyPrime + 32, 0x36, 32);
	} else {
		for (uint8_t i = 0; i < 64; i++) {
			keyPrime[i] = i < keyLength ? key[i] ^ 0x36u : 0x36;
		}
	}
}

void hmac_prepare(const uint8_t *key, uint16_t keyLength, uint64_t messageByteLength) {
	hmac_key_prime(key, keyLength);
	sm3_init();
	targetByteLength = sm3_get_padded_byte_length(messageByteLength);
	messageLength = messageByteLength;
	processedLength = 0;
}

void hmac_update(const uint8_t *msg) {
	sm3_update(msg, processedLength, messageLength * 8);
	processedLength += 64;
}

uint32_t *hmac_finalize() {
	memcpy(buf, keyPrime, 64);
	for (uint8_t i = 0; i < 64; i++) {
		keyPrime[i] ^= 0x36u;
		keyPrime[i] ^= 0x5cu;
	}
	memcpy(buf + 64, sm3_finalize(), 32);
	return sm3_digest(buf, 96 * 8);
}
